package com.ics.cmsadmin.modules.agent.service.impl;

import com.ics.cmsadmin.frame.constant.Constants;
import com.ics.cmsadmin.frame.core.annotation.CacheDbMember;
import com.ics.cmsadmin.frame.core.annotation.ClearDbMember;
import com.ics.cmsadmin.frame.core.bean.LoginSearchBean;
import com.ics.cmsadmin.frame.core.bean.PageBean;
import com.ics.cmsadmin.frame.core.bean.PageResult;
import com.ics.cmsadmin.frame.core.bean.TwoTupleBean;
import com.ics.cmsadmin.frame.core.enums.ApiResultEnum;
import com.ics.cmsadmin.frame.core.enums.CacheGroupEnum;
import com.ics.cmsadmin.frame.core.exception.CmsException;
import com.ics.cmsadmin.frame.core.service.LoginBaseDataService;
import com.ics.cmsadmin.modules.agent.bean.*;
import com.ics.cmsadmin.modules.agent.service.AgentDaySummaryService;
import com.ics.cmsadmin.modules.agent.steward.AgentUtils;
import com.ics.cmsadmin.modules.auth.steward.AuthServices;
import com.ics.cmsadmin.modules.basic.bean.StudentBean;
import com.ics.cmsadmin.modules.basic.dao.StudentDao;
import com.ics.cmsadmin.modules.system.emums.RegisterKeyValueEnum;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.ics.cmsadmin.modules.agent.steward.AgentRepositories.agentDaySummaryDao;
import static com.ics.cmsadmin.modules.agent.steward.AgentRepositories.applyWithdrawCashDao;
import static com.ics.cmsadmin.modules.agent.steward.AgentServices.agentAccountService;
import static com.ics.cmsadmin.modules.agent.steward.AgentServices.agentInfoService;
import static com.ics.cmsadmin.modules.system.steward.SystemServices.registerService;

@Service
@Log4j2
public class AgentDaySummaryServiceImpl implements AgentDaySummaryService {

    @Resource
    private StudentDao studentDao;
    @ClearDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY)
    @Override
    public boolean daySummary() {
        return daySummary(null);
    }

    @ClearDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY)
    @Override
    public boolean daySummary(String summaryDate) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            if (StringUtils.isNotBlank(summaryDate)){
                simpleDateFormat.parse(summaryDate);
            }
        }catch (Exception e){
            log.error("日期格式不正确(格式：yyyy-MM-dd)");
            throw new CmsException(ApiResultEnum.VALIDATE_ERROR, "日期格式不正确(格式：yyyy-MM-dd)");
        }
        String formatDate = StringUtils.isNotBlank(summaryDate) ? summaryDate :
            simpleDateFormat.format(DateUtils.addDays(new Date(), -1));
        agentDaySummaryDao.insertAgentBaseDaySummery(formatDate);
        agentDaySummaryDao.summeryFuns(formatDate);
        agentDaySummaryDao.summeryBuyerAndOrderMoney(formatDate);
        agentDaySummaryDao.summeryChildAgent(formatDate);
        agentDaySummaryDao.summeryChildAgentFuns(formatDate);
        agentDaySummaryDao.summeryChildAgentBuyerAndOrderMoney(formatDate);
        agentDaySummaryDao.summerySelfShareMoney(formatDate);
        agentDaySummaryDao.summeryParentShareMoney(formatDate);
        agentDaySummaryDao.summeryChildShareMoney(formatDate);
        agentDaySummaryDao.summeryAllShareMoney(formatDate);
        return true;
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class)
    @Override
    public PageResult<AgentDaySummaryBean> listAgentSummaryByLoginUserId(AgentInfoBean agentBean, String loginUserId, PageBean pageBean) {
        return LoginBaseDataService.listByLogin(agentBean, loginUserId, pageBean,
            agentDaySummaryDao::countAgentSummary,
            agentDaySummaryDao::listAgentSummary);
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class, timeToLive = 3600)
    @Override
    public AgentDaySummaryBean queryMyDistributorInfo(String loginUserId) {
        if (StringUtils.isBlank(loginUserId)) {
            return null;
        }
        LoginSearchBean loginSearchBean = AuthServices.accessService.queryLoginInfoByLoginUserId(loginUserId);
        if (loginSearchBean == null) {
            return null;
        }
        // 下级今日购买人数
        int childrenBuyerNum = agentDaySummaryDao.countChildrenBuyerNumToday(loginSearchBean);
        // 下级购买总人数
        int childrenAllBuyerNum = agentDaySummaryDao.countChildrenAllBuyerNum(loginSearchBean);
        // 下级今日关注人数
        int childrenFansNum = agentDaySummaryDao.countChildrenFansNumToday(loginSearchBean);
        // 下级关注总人数
        int childrenAllFansNum = agentDaySummaryDao.countChildrenAllFansNum(loginSearchBean);
        // 下级获取的总收益
        BigDecimal allShareMoney = agentDaySummaryDao.countChildrenAllShareMoney(loginSearchBean);
        return AgentDaySummaryBean.builder()
            .buyerNewly(childrenBuyerNum)
            .buyerCusm(childrenAllBuyerNum)
            .funsNewly(childrenFansNum)
            .funsCusm(childrenAllFansNum)
            .allShareMoneyCusm(allShareMoney)
            .build();
    }

    /**
     * 检查时间范围(默认为前7天)
     */
    private void checkDefaultDateRange(AgentInfoBean bean) {
        Date startDate, endDate;
        Date yesterday = DateUtils.addDays(new Date(), -1);
        try {
            startDate = DateUtils.parseDate(bean.getStartCreateTime(), "yyyy-MM-dd");
        }catch (Exception e){
            startDate = DateUtils.addDays(new Date(), -7);
        }
        try {
            endDate = DateUtils.parseDate(bean.getEndCreateTime(), "yyyy-MM-dd");
        }catch (Exception e){
            endDate = yesterday;
        }

        if (endDate.after(yesterday)) {
            endDate = yesterday;
        }
        if (startDate.after(endDate)){
            startDate = DateUtils.addDays(endDate, -6);
        }
        bean.setStartCreateTime(DateFormatUtils.format(startDate, "yyyy-MM-dd"));
        bean.setEndCreateTime(DateFormatUtils.format(endDate, "yyyy-MM-dd"));
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class)
    @Override
    public List<AgentDaySummaryBean> listDistributorSummary(AgentInfoBean bean, String loginUserId) {
        if (bean == null){
            bean = new AgentInfoBean();
        }
        LoginSearchBean loginSearchBean = AuthServices.accessService.queryLoginInfoByLoginUserId(loginUserId);
        BeanUtils.copyProperties(loginSearchBean, bean);
        checkDefaultDateRange(bean);
        List<AgentDaySummaryBean> agentDaySummaryBeans = agentDaySummaryDao.listDistributorSummary(bean);
        return AgentUtils.optimizeResult(agentDaySummaryBeans, bean.getStartCreateTime(), bean.getEndCreateTime());
    }


    @Override
    public TwoTupleBean<AgentDaySummaryBean, AgentAccountBean> queryMyRevenue(String loginUserId) {
        AgentInfoBean agentInfoBean = agentInfoService.queryByUserId(loginUserId);
        if (agentInfoBean == null) {
            return null;
        }
        String agentNo = agentInfoBean.getAgentNo();
        AgentDaySummaryBean agentDaySummaryBean = Optional.ofNullable(agentDaySummaryDao.summaryShareMoney(agentNo))
            .orElse(new AgentDaySummaryBean());
        AgentAccountBean agentAccountBean = agentAccountService.queryByAgentNo(agentNo);
        return new TwoTupleBean<>(agentDaySummaryBean, agentAccountBean);
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class)
    @Override
    public List<AgentDaySummaryBean> listAgentDaySummary(AgentInfoBean bean) {
        if (bean == null){
            return AgentUtils.optimizeResult();
        }
        checkDefaultDateRange(bean);
        List<AgentDaySummaryBean> agentDaySummaryBeans = agentDaySummaryDao.listAgentDaySummary(bean);
        return AgentUtils.optimizeResult(agentDaySummaryBeans, bean.getStartCreateTime(), bean.getEndCreateTime());
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class)
    @Override
    public PageResult<AgentDaySummaryBean> queryMyRevenue4Table(AgentInfoBean bean,
                                                                String loginUserId,
                                                                PageBean pageBean) {
        AgentInfoBean agentInfoBean = agentInfoService.queryByUserId(loginUserId);
        if (agentInfoBean == null){
            return new PageResult<>();
        }
        bean.setAgentNo(agentInfoBean.getAgentNo());
        Long count = agentDaySummaryDao.countMyRevenue4Table(bean);
        if (count == 0) {
            return new PageResult<>();
        }
        return new PageResult<>(agentDaySummaryDao.listMyRevenue4Table(bean, pageBean), count);
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class, timeToLive = 3600)
    @Override
    public AgentDaySummaryBean queryMyStudentInfo(String loginUserId) {
        AgentInfoBean agentInfoBean = agentInfoService.queryByUserId(loginUserId);
        if (agentInfoBean == null) {
            return null;
        }
        String agentNo = agentInfoBean.getAgentNo();
        AgentDaySummaryBean agentDaySummaryBean = Optional.ofNullable(agentDaySummaryDao.summaryShareMoney(agentNo))
            .orElse(new AgentDaySummaryBean());
        // 今日购买人数
        int buyerNewly = agentDaySummaryDao.countBuyerNumToday(agentNo);
        // 购买总人数
        int buyerCusm = agentDaySummaryDao.countAllBuyerNum(agentNo);
        // 今日关注人数
        int funsNewly = agentDaySummaryDao.countFansNumToday(agentNo);
        // 关注总人数
        int funsCusm = agentDaySummaryDao.countAllFansNum(agentNo);
        agentDaySummaryBean.setBuyerNewly(buyerNewly);
        agentDaySummaryBean.setBuyerCusm(buyerCusm);
        agentDaySummaryBean.setFunsNewly(funsNewly);
        agentDaySummaryBean.setFunsCusm(funsCusm);
        return agentDaySummaryBean;
    }

    @Override
    public PageResult<Map<String, Object>> queryMyStudent4Table(AgentInfoBean bean, String loginUserId, PageBean pageBean) {
        AgentInfoBean agentInfoBean = agentInfoService.queryByUserId(loginUserId);
        if (agentInfoBean == null) {
            return null;
        }
        bean.setAgentNo(agentInfoBean.getAgentNo());
        Long count = agentDaySummaryDao.counyMyStudent4Table(bean);
        if (count == 0) {
            return new PageResult<>();
        }
        return new PageResult<>(agentDaySummaryDao.listMyStudent4Table(bean, pageBean), count);
    }

    @Override
    public Map<String, String> queryMyWithdrawInfo(String loginUserId) {
        AgentInfoBean agentInfoBean = agentInfoService.queryByUserId(loginUserId);
        if (agentInfoBean == null) {
            return null;
        }
        AgentAccountBean agentAccountBean = agentAccountService.queryByAgentNo(agentInfoBean.getAgentNo());
        int applyWithdrawCashIntervalDay = registerService.queryRegisterValue(RegisterKeyValueEnum.APPLY_WITHDRAW_CASH_INTERVAL_DAY, Integer::valueOf);
        int maxAcceptWithdrawCashNum = registerService.queryRegisterValue(RegisterKeyValueEnum.WITHDRAW_CASH_INTERVAL_MAX_ACCEPT_COUNT, Integer::valueOf);
        long acceptSuccessCount = applyWithdrawCashDao.count(ApplyWithdrawCashBean
            .builder()
            .agentNo(agentAccountBean.getAgentNo())
            .status(Constants.APPLY_WITHDRAW_CASH_ACCEPT_SUCCESS)
            .startUpdateTime(org.apache.commons.lang.time.DateFormatUtils.format(org.apache.commons.lang.time.DateUtils.addDays(new Date(), -maxAcceptWithdrawCashNum), "yyyy-MM-dd 00:00:00"))
            .build());
        long submitSuccess = applyWithdrawCashDao.count(ApplyWithdrawCashBean
            .builder()
            .agentNo(agentAccountBean.getAgentNo())
            .status(Constants.APPLY_WITHDRAW_CASH_SUBMIT)
            .build());
        long count = maxAcceptWithdrawCashNum - acceptSuccessCount - submitSuccess;
        count = count > 0 ? count : 0;
        Map<String, String> result = new HashMap<>();
        result.put("applyWithdrawCashIntervalDay", applyWithdrawCashIntervalDay + "");
        result.put("maxAcceptWithdrawCashNum",count + "");
        result.put("availableBalance", agentAccountBean.getAvailableBalance() + "");
        return result;
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class, timeToLive = 3600)
    @Override
    public AgentDaySummaryBean queryMyDistributorDetailInfo(String agentNo) {
        AgentInfoBean agentInfoBean = agentInfoService.queryById(agentNo);
        // 今日购买人数agentInfoService.
        int buyerNewly = agentDaySummaryDao.countBuyerNumToday(agentNo);
        // 购买总人数
        int buyerCusm = agentDaySummaryDao.countAllBuyerNum(agentNo);
        // 今日关注人数
        int funsNewly = agentDaySummaryDao.countFansNumToday(agentNo);
        // 关注总人数
        int funsCusm = agentDaySummaryDao.countAllFansNum(agentNo);
        BigDecimal parentShareMoneyNewly = agentDaySummaryDao.countParentShareMoneyToday(agentNo);
        BigDecimal parentShareMoneyCusm = agentDaySummaryDao.parentAllParentShareMoneyCusm(agentNo);
        StudentBean studentBean = studentDao.findLatelyStudentByAgentNo(agentNo);
        String studentCreateTime = studentBean == null ? "" : DateFormatUtils.format(studentBean.getCreateTime(), "yyyy-MM-dd HH:mm:ss");
        return AgentDaySummaryBean.builder()
            .createTime(agentInfoBean.getCreateTime())
            .buyerNewly(buyerNewly)
            .buyerCusm(buyerCusm)
            .funsNewly(funsNewly)
            .funsCusm(funsCusm)
            .parentShareMoneyNewly(parentShareMoneyNewly)
            .parentShareMoneyCusm(parentShareMoneyCusm)
            .summaryDay(studentCreateTime)
            .build();
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class)
    @Override
    public PageResult<AgentDaySummaryBean> pageAgentDaySummary(AgentInfoBean agentInfoBean, PageBean pageBean) {
        long count = agentDaySummaryDao.countAgentDaySummary(agentInfoBean);
        if (count == 0){
            return new PageResult<>();
        }
        return new PageResult<>(agentDaySummaryDao.listAgentDaySummary(agentInfoBean, pageBean), count);
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = AgentDaySummaryBean.class)
    @Override
    public AgentDaySummaryBean queryMyStudentDetailInfo(String userId) {
        if (StringUtils.isBlank(userId)) {
            return null;
        }
        StudentBean studentBean = studentDao.queryById(userId);
        if (studentBean == null){
            return null;
        }
        // 今日购买量
        int buyerNewly = agentDaySummaryDao.countOrderNumTodayByStudent(userId);
        // 购买总量
        int buyerCusm = agentDaySummaryDao.countAllOrderNumByStudent(userId);
        // 购课总金额
        BigDecimal orderMoneyCusm = agentDaySummaryDao.sumAllOrderMoneyByStudent(userId);
        // 学生推广总收益
        BigDecimal parentShareMoneyCusm = agentDaySummaryDao.sumShareMoneyByStudent(userId);
        return AgentDaySummaryBean.builder()
            .createTime(studentBean.getCreateTime())
            .buyerNewly(buyerNewly)
            .buyerCusm(buyerCusm)
            .orderMoneyCusm(orderMoneyCusm)
            .parentShareMoneyCusm(parentShareMoneyCusm)
            .build();
    }

    @CacheDbMember(group = CacheGroupEnum.CACHE_AGENT_DAY_SUMMARY, returnClass = StudentOrderBean.class)
    @Override
    public PageResult<StudentOrderBean> listMyStudentBuyOrderInfo(StudentOrderBean studentOrderBean, PageBean pageBean) {
        if (studentOrderBean == null || StringUtils.isBlank(studentOrderBean.getUserId())) {
            return new PageResult<>();
        }
        long count = agentDaySummaryDao.countMyStudentBuyOrderInfo(studentOrderBean);
        if (count == 0){
            return new PageResult<>();
        }
        return new PageResult<>(agentDaySummaryDao.listMyStudentBuyOrderInfo(studentOrderBean, pageBean), count);
    }
}
